import {
  POWER_STATE,
  POWER_STATES,
  OPERATION_KEY,
  DOOR_STATES,
  DOOR_STATE,
  CHILD_MODE,
  LOCAL_CONTROL_ACTIVE,
  REMOTE_CONTROL_ACTIVE,
  REMOTE_CONTROL_START_ALLOWED,
  SOFTWARE_UPDATE_AVAILABLE,
  PRESENT,
  OPERATION_STATES,
  SOFTWARE_UPDATE_SUCCESSFUL,
} from '@/constants/Command'
import { onceObserve, requestSubscribeUsingComplete, showLoading, toPage } from '@/utils/mpHelper'
import { defineStore } from 'pinia'
import { createDatasource, useWorker, useRemote, wrapSafeActions } from '@/controller/base/index'
import { RemoteTypes } from '@/controller/base/remote'
import type { BaseController } from './definition'
import { createNoticeState, NoticeActions, NoticeGetters, useNoticeEffects } from '../common/Notice/notice'
import { createProgramState, ProgramActions, ProgramGetters } from '../common/Program/program'
import netconfig from '@/config/netconfig'
import { WebsocketManager } from '@/utils/socket/WebsocketManager'
import { DetailScene } from './constants'
import { useErrorNotice } from '@/controller/common/ErrorHandler/useErrorNotice'
import { trackEvent, TrackType } from '@/dataReport/tracks'
import { safeTrack } from '@/dataReport/dataReportUtil'
import { removeControllerContext, setControllerContext } from '../common/context'
import type { OemMessage } from '@/utils/socket/types'

/**
 * 初始化数据
 */
export const createBaseState: () => BaseController.State = () => ({
  _datasource: createDatasource(),
  ...createNoticeState(),
  ...createProgramState(),
  // 场景
  detailScene: DetailScene.Default,
  remoteControl: true,
  remoteStart: true,
  isOffline: null,
  powerState: null,
  localOperating: false,
  hasChildLock: false,
  childLockOn: false,
  doorState: DOOR_STATES.CLOSED,
  operationState: null,
  updateDetected: false,
  isStartingUp: false, // 正在开机中
  isShuttingDown: false, // 正在关机中
})
export const BaseGetters: BaseController.Getters = {
  ...NoticeGetters,
  ...ProgramGetters,
  isVirtualAppliance() {
    return this.detailScene === DetailScene.VirtualAppliance
  },
  detail() {
    return this._datasource.detail
  },
  coverImage() {
    const vib = this.detail?.vib
    return vib ? `${netconfig.PHOTO_IMAGE}${vib}/${vib}.png` : ''
  },
  isSMM() {
    return this.detail?.deviceSubType === 'SMM'
  },
}
export const BaseActions: BaseController.Actions = {
  ...ProgramActions,
  ...NoticeActions,

  // 报错特殊处理
  specialErrorInterceptor: () => Promise.resolve(false),
  specialAccessableCheck: () => true,

  /**
   * Actions
   */
  async togglePowerState() {
    const remote = useRemote(this)
    const powerState = this.powerState !== POWER_STATES.ON ? POWER_STATES.ON : POWER_STATES.OFF
    trackEvent(
      'appliance_setting',
      { setting_key: POWER_STATE, setting_value: powerState },
      TrackType.ApplianceDetail,
      'Appliance.Detail.Power.Control'
    )

    // 设置电源操作中状态
    if (this.powerState === POWER_STATES.ON) {
      this.isShuttingDown = true
    } else {
      this.isStartingUp = true
    }

    // 设置电源状态 (下发状态方法不能await，防止下发过程中电源状态变化，错过监听)
    remote.setSetting(POWER_STATE, powerState)

    // 电源状态切换或断电时 都将关闭Loading
    await Promise.race([onceObserve(() => this.powerState), onceObserve(() => this.isOffline)])
    this.isShuttingDown = false
    this.isStartingUp = false
  },
  async changeChildLock(childLockOn: boolean) {
    const remote = useRemote(this)
    trackEvent(
      'appliance_setting',
      { setting_key: CHILD_MODE, setting_value: childLockOn },
      TrackType.ApplianceDetail,
      'Appliance.Detail.Childlock.Control'
    )
    await showLoading(() => remote.setSetting(CHILD_MODE, childLockOn))
  },
}

/**
 * 组合API
 */
const useStore = defineStore<'BaseAppliance', BaseController.State, BaseController.Getters, BaseController.Actions>(
  'BaseAppliance',
  {
    state: createBaseState,
    getters: BaseGetters,
    actions: BaseActions,
  }
)

// 组件使用
export function useBaseApplianceControl(): BaseController.Control {
  const store = useStore() as BaseController.Store
  const worker = useWorker<BaseController.Store>(store)
  const remote = useRemote(store)
  return { store, worker, remote }
}

export function createBaseApplianceControl(
  control: BaseController.Control,
  options: BaseController.ConstructorOptions
): BaseController.Control {
  if (!control) {
    control = useBaseApplianceControl()
  }

  const { store, worker, remote } = control

  // Store
  store.$reset()

  // Remote
  remote.init()
  remote.setRemoteType(options.remoteType)
  WebsocketManager.instance.connectWebsocket()

  // 监听Websocket
  const websocketInstance =
    options.remoteType === RemoteTypes.Inhouse
      ? WebsocketManager.instance.inhouseWebsocket
      : WebsocketManager.instance.oemWebsocket
  remote.useMessageListener(websocketInstance)

  // Worker
  worker.init()

  /**
   * 模块初始化
   */
  useBaseEffects(control, options)

  return control
}

function useBaseEffects(control: BaseController.Control, options: BaseController.ConstructorOptions) {
  // 监听绑定
  useBaseBinding(control, options)
  // 通知栏
  useNoticeEffects(control, options)
  // 添加接口错误监听
  useErrorNotice()
  // 记录当前Controller Context
  control.worker.onLoad(async () => setControllerContext(control))
  control.worker.onReset(() => removeControllerContext(control.store._datasource.haId))
  // 在线离线刷新
  watch(
    () => control.store.isOffline,
    async (currentOfflineState, previousOfflineState) => {
      // 阻止首次进入触发刷新
      if (previousOfflineState === null) return

      await control.worker.triggerOnLoad()
      await control.worker.triggerOnShow()
    }
  )
  // 跳转家电设置页中转
  control.worker.onLoad(async (query) => {
    const shouldJumpToSetting = query?.toSetting === 'true'
    if (!shouldJumpToSetting) return

    // 一次性消息订阅
    await requestSubscribeUsingComplete([netconfig.DeviceStateId])
    // 跳转家电设置页
    const { haId, vib, type } = control.store._datasource
    const name = control?.store.detail?.name || ''
    const guest = control.store.detail?.guest
    const connected = !control.store.detail?.connected
    const remoteControl = control.store.remoteControl
    const remoteStart = control.store.remoteStart
    const isVirtual = control.store.isVirtualAppliance
    return toPage('/pages/appliance/settings/applianceSettings', {
      haId,
      vib,
      type,
      guest,
      connected,
      remoteControl,
      remoteStart,
      isVirtual,
      name,
    })
  })

  // 埋点相关
  control.worker.onLoad(async () => {
    if (control.store.detail?.operationState === OPERATION_STATES.RUN) {
      safeTrack(() => {
        trackEvent('check_running_status', {}, TrackType.ApplianceDetail, 'Appliance.Deatail.Page.Show')
      })
    }
  })
}

function useBaseBinding(control: BaseController.Control, options: BaseController.ConstructorOptions) {
  const { store, worker, remote } = control

  const isInhouse = remote.remoteType === RemoteTypes.Inhouse

  // 是否离线
  worker.useDetailBinding('isOffline', (detail) => !detail.connected)
  remote.addBatchObserve({
    acceptNullMessage: true,
    handler: (msg, remote, msgContext) => {
      if (!msgContext) return
      if (msgContext.type === 'DISCONNECTED') {
        store.isOffline = true
      } else if (msgContext.type === 'CONNECTED') {
        store.isOffline = false
      }
    },
  })
  // 电源
  worker.useGetValueBinding('powerState', {
    key: POWER_STATE,
    from: 'setting',
  })
  // 远程控制
  worker.useGetValueBinding('remoteControl', {
    key: REMOTE_CONTROL_ACTIVE,
    from: isInhouse ? 'status' : 'setting',
    patcher: options?.remoteControlPatcher,
  })

  // 远程启动
  worker.useGetValueBinding('remoteStart', {
    key: REMOTE_CONTROL_START_ALLOWED,
    from: isInhouse ? 'status' : 'setting',
    patcher: options?.remoteStartPatcher,
  })
  // 远程控制、远程启动切换时 刷新commands查询是否支持暂停、停止
  remote.addObserve({
    [REMOTE_CONTROL_ACTIVE]: () => control.remote.loadSupportCommands(),
    [REMOTE_CONTROL_START_ALLOWED]: () => control.remote.loadSupportCommands(),
  })
  // 本地操作 (仅监听websocket推送)
  worker.useGetValueBinding('localOperating', {
    key: LOCAL_CONTROL_ACTIVE,
    from: 'event',
    useMessage: 'only',
  })
  // 门状态
  worker.useGetValueBinding('doorState', {
    key: DOOR_STATE,
    from: isInhouse ? 'status' : 'setting',
  })
  // 童锁
  worker.useHasKeyBinding('hasChildLock', {
    key: CHILD_MODE,
    from: 'setting',
  })
  worker.useGetValueBinding('childLockOn', {
    key: CHILD_MODE,
    from: 'setting',
  })

  /**
   * 操作状态
   */
  worker.useDetailBinding('operationState', (detail) => {
    if (detail.operationState) {
      return detail.operationState as OPERATION_STATES
    }
  })

  if (remote.remoteType === RemoteTypes.Inhouse) {
    worker.useGetValueBinding('operationState', {
      key: OPERATION_KEY,
      from: 'status',
    })
  } else if (remote.remoteType === RemoteTypes.Oem) {
    worker.useGetValueBinding('operationState', {
      key: OPERATION_KEY,
      from: 'event',
      useMessage: 'only',
      patcher(patchState, reference) {
        patchState.operationState = (reference.item as OemMessage.EnumItem).displayValue as OPERATION_STATES
      },
    })
  }

  // 固件升级
  if (options.remoteType === RemoteTypes.Inhouse) {
    worker.useGetValueBinding('updateDetected', {
      key: SOFTWARE_UPDATE_AVAILABLE,
      from: 'event',
      patcher: (patchState, reference) => {
        patchState.updateDetected = reference.value === PRESENT
      },
    })
    worker.useGetValueBinding('updateDetected', {
      key: SOFTWARE_UPDATE_SUCCESSFUL,
      from: 'event',
      patcher: (patchState, reference) => {
        patchState.updateDetected = false
      },
    })
  }
}
